package com.summer.bilibili.listener;

import cn.hutool.core.util.StrUtil;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 监听redis中的key到期，注意tomcat关闭状态下无法被通知
 */
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
    // KeyExpirationEventMessageListener
    // Spring Data Redis提供的基类，用于监听Redis的键过期事件（__keyevent@*__:expired）
    /**
     * RedisKey : 处理函数
     */
    //线程安全的映射表，存储 Redis键 → 处理函数的对应关系
    private final Map < String, Runnable > handlers = new ConcurrentHashMap <> ( );

    // 依赖注入
    public RedisKeyExpirationListener ( RedisMessageListenerContainer listenerContainer ) {
        super ( listenerContainer );
    }

    // 供外部注册键与处理逻辑的入口方法
    // 当redisKey过期时，执行一次handler
    public void handleOnce ( String redisKey , Runnable handler ) {
        handlers.put ( redisKey , handler );
    }

    // 接收Redis过期事件并执行回调
    @Override
    public void onMessage ( Message message , byte[] pattern ) {
        String redisKey = new String ( message.getBody ( ) ); // 获取Redis键
        if ( StrUtil.isNotBlank ( redisKey ) ) {    // 键不为空，避免空指针异常
            Runnable handler = handlers.remove ( redisKey ); // 获取对应的处理函数，删除该键
            if ( handler != null ) { // 处理函数不为空
                handler.run ( ); // 同步执行处理函数
            }
        }
    }
}
